use tauri;
use tauri::Emitter;
use crate::models::state::{MakeCallArgs, MakeCallResult, ConnectionResult, GLOBAL_STATE, CallStatus};
use sip_auth::DigestAuthenticator;
use sip_ua::{CallEvent, MediaEvent, RtcMediaBackend};
use rtc::rtp_session::SendRtpPacket;
use rtc::sdp::{RtcpMuxPolicy, TransportType};
use rtc::{sdp::{Codecs, SdpSession, SdpSessionConfig}, OpenSslContext};
use sdp_types::{Direction, MediaType};
use crate::utils::network::get_local_ip_for_target;
use crate::services::audio::{AudioDecoder, AudioEncoder};
use tokio::time::interval;
use crate::services::audio::AudioRecorder;
use tokio::sync::Mutex as AsyncMutex;
use std::collections::VecDeque;
use std::sync::mpsc as std_mpsc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::time::Duration;

pub struct CallRuntimeService;

impl CallRuntimeService {
    pub fn emit_call_event(app: &tauri::AppHandle, payload: serde_json::Value) { let _ = app.emit("call_event", payload); }

    pub async fn make_call(app: tauri::AppHandle, args: MakeCallArgs) -> Result<MakeCallResult, String> {
        let target = args.target.trim();
        if target.is_empty() { return Err("目标号码不能为空".to_string()); }
        let (registration, credentials, last_host) = { let state = GLOBAL_STATE.lock().await; let reg = state.registration.clone().ok_or_else(|| "尚未连接SIP服务器，请先登录".to_string())?; let creds = state.last_credentials.clone().ok_or_else(|| "缺少认证信息，请重新连接后重试".to_string())?; (reg, creds, state.last_host.clone()) };
        let target_host = { let mut s = target.to_string(); if let Some(idx) = s.find(':') { if s[..idx].eq_ignore_ascii_case("sip") { s = s[idx + 1..].to_string(); } } let host = if let Some(at) = s.rfind('@') { s[at + 1..].to_string() } else { last_host.clone().ok_or_else(|| "无法推断目标主机，请在号码中包含 @host 或先连接服务器".to_string())? }; host.split(';').next().unwrap_or(&host).to_string() };
        let bind_ip = get_local_ip_for_target(&target_host)?;
        let mut sdp_cfg = SdpSessionConfig::default();
        sdp_cfg.offer_transport = TransportType::Rtp; sdp_cfg.offer_avpf = false; sdp_cfg.rtcp_mux_policy = RtcpMuxPolicy::Negotiate;
        let mut sdp_session = SdpSession::new(OpenSslContext::try_new().map_err(|e| format!("OpenSSL 初始化失败: {}", e))?, bind_ip.parse().map_err(|_| format!("本地IP解析失败: {}", bind_ip))?, sdp_cfg);
        let audio = sdp_session.add_local_media(Codecs::new(MediaType::Audio).with_codec(rtc::sdp::Codec::PCMU).with_codec(rtc::sdp::Codec::PCMA).with_dtmf(), Direction::SendRecv).ok_or_else(|| "SDP 音频媒体创建失败".to_string())?;
        sdp_session.add_media(audio, Direction::SendRecv);
        let call_record = crate::services::call::CallService::new_outgoing_record(target);
        let call_id = call_record.id.clone();
        if let Err(e) = crate::services::call::CallService::add_record(call_record).await { log::error!("保存通话记录失败: {}", e); }
        Self::emit_call_event(&app, serde_json::json!({"type":"dialing","target":target,"bind_ip":bind_ip,"target_host":target_host,"call_id":call_id}));
        let stop_flag = std::sync::Arc::new(AtomicBool::new(false));
        { let mut state = GLOBAL_STATE.lock().await; state.current_call_stop = Some(stop_flag.clone()); }
        let mut outbound = registration.begin_call(target.to_string(), DigestAuthenticator::new(credentials.clone()), RtcMediaBackend::new(sdp_session)).await.map_err(|e| format!("发起呼叫失败: {}", e))?;
        log::info!("已发起呼叫，等待网络响应");
        let app_for_loop = app.clone();
        let stop_for_loop = stop_flag.clone();
        let call_id_for_loop = call_id.clone();
        tauri::async_runtime::spawn(async move {
            // 创建一个任务来监听停止标志，在呼叫建立前取消呼叫
            let stop_for_cancel = stop_for_loop.clone();
            let app_cancel = app_for_loop.clone();
            let call_id_cancel = call_id_for_loop.clone();

            // 使用 tokio::select! 来同时等待呼叫完成和取消信号（优先处理取消）
            let result = tokio::select! {
                biased;
                // 优先检测取消标志（10ms 轮询）
                _ = async {
                    loop {
                        if stop_for_cancel.load(std::sync::atomic::Ordering::SeqCst) { break; }
                        tokio::time::sleep(Duration::from_millis(10)).await;
                    }
                } => {
                    log::info!("尝试取消呼叫 (pre-finish)");
                    match outbound.cancel().await {
                        Ok(_) => {
                            log::info!("成功发送 CANCEL 请求");
                            let _ = crate::services::call::CallService::update_status(&call_id_cancel, CallStatus::Cancelled, None).await;
                            let _ = app_cancel.emit("call_event", serde_json::json!({"type":"terminated"}));
                        }
                        Err(e) => {
                            log::warn!("发送 CANCEL 失败: {}", e);
                            let _ = crate::services::call::CallService::update_status(&call_id_cancel, CallStatus::Cancelled, None).await;
                            let _ = app_cancel.emit("call_event", serde_json::json!({"type":"terminated"}));
                        }
                    }
                    return; // 直接返回
                }
                // 等待呼叫完成
                result = outbound.wait_for_completion() => {
                    log::info!("呼叫完成");
                    Some(result)
                }
            };

            if let Some(completion_result) = result {
                match completion_result {
                    Ok(unacked) => {
                        // 在完成建立呼叫前，再次监听停止标志，必要时发送 CANCEL
                        let finish_result = tokio::select! {
                            biased;
                            _ = async {
                                loop {
                                    if stop_for_loop.load(std::sync::atomic::Ordering::SeqCst) { break; }
                                    tokio::time::sleep(Duration::from_millis(10)).await;
                                }
                            } => {
                                log::info!("finish 等待阶段检测到停止标志，尝试发送 CANCEL");
                                match outbound.cancel().await {
                                    Ok(_) => log::info!("(finish阶段) 成功发送 CANCEL 请求"),
                                    Err(e) => log::warn!("(finish阶段) 发送 CANCEL 失败: {}", e),
                                }
                                let _ = crate::services::call::CallService::update_status(&call_id_for_loop, CallStatus::Cancelled, None).await;
                                let _ = app_for_loop.emit("call_event", serde_json::json!({"type":"terminated"}));
                                return; // 不再继续建立通话
                            }
                            res = unacked.finish() => { res }
                        };

                        let _ = crate::services::call::CallService::update_status(&call_id_for_loop, CallStatus::Connected, None).await;
                        let _ = app_for_loop.emit("call_event", serde_json::json!({"type":"answered"}));
                        match finish_result {
                            Ok(mut call) => {
                                let app_inside = app_for_loop.clone();
                                let audio_tx = Self::spawn_audio_player_thread(stop_for_loop.clone());
                                loop { 
                                    tokio::select! {
                                        result = call.run() => {
                                            match result {
                                                Ok(CallEvent::Internal(ev)) => { let _ = call.handle_internal_event(ev).await; }
                                                Ok(CallEvent::Media(media_ev)) => match media_ev {
                                                    MediaEvent::ReceiverAdded { mut receiver, codec } => {
                                                        let mut decoder = AudioDecoder::new(&codec.name, codec.clock_rate);
                                                        let tx = audio_tx.clone();
                                                        let stop_for_rx = stop_for_loop.clone();
                                                        tokio::spawn(async move {
                                                            let mut cnt = 0usize; 
                                                            while !stop_for_rx.load(std::sync::atomic::Ordering::SeqCst) { 
                                                                if let Some(pkt) = receiver.recv().await { 
                                                                    let payload = pkt.payload.as_ref(); 
                                                                    if !payload.is_empty() { 
                                                                        let decoded = decoder.decode(payload); 
                                                                        if !decoded.is_empty() { 
                                                                            let _ = tx.send((decoded, codec.clock_rate, codec.channels.unwrap_or(1) as u32)); 
                                                                        } 
                                                                        cnt += 1; 
                                                                        if cnt % 50 == 0 { 
                                                                            log::debug!("接收音频包: {} / size={}B", cnt, payload.len()); 
                                                                        } 
                                                                    } 
                                                                } else { 
                                                                    break; 
                                                                } 
                                                            } 
                                                        });
                                                    }
                                                    MediaEvent::SenderAdded { mut sender, codec } => {
                                                        let max_mtu = call.media().sdp_session().max_payload_size_for_media(sender.media_id()).unwrap_or(1200);
                                                        let encoder = AudioEncoder::new(&codec.name, codec.clock_rate, codec.channels.unwrap_or(1) as u32);
                                                        let queue: std::sync::Arc<tokio::sync::Mutex<VecDeque<Vec<i16>>>> = std::sync::Arc::new(tokio::sync::Mutex::new(VecDeque::new()));
                                                        let q2 = queue.clone();
                                                        let _mic = Self::spawn_mic_thread(codec.clock_rate, codec.channels.unwrap_or(1) as u32, q2, stop_for_loop.clone(), 20);
                                                        let stop_for_tx = stop_for_loop.clone();
                                                        tokio::spawn(async move {
                                                            let mut tick = interval(Duration::from_millis(20));
                                                            let mut cnt = 0usize;
                                                            let frame_samples = Self::compute_frame_samples(codec.clock_rate, 20);
                                                            loop {
                                                                if stop_for_tx.load(std::sync::atomic::Ordering::SeqCst) { break; }
                                                                let instant = tick.tick().await;
                                                                let samples = { let mut q = queue.lock().await; q.pop_front().unwrap_or_else(|| vec![0i16; frame_samples]) };
                                                                let frame = Self::make_exact_frame(samples, frame_samples);
                                                                let encoded = encoder.encode(&frame);
                                                                let payload = if encoded.len() > max_mtu { &encoded[..max_mtu] } else { &encoded };
                                                                if let Err(e) = sender.send(SendRtpPacket::new(instant.into(), codec.pt, payload.to_vec().into())).await { 
                                                                    log::error!("发送RTP包失败: {}", e); 
                                                                    break; 
                                                                }
                                                                cnt += 1; 
                                                                if cnt % 50 == 0 { 
                                                                    log::debug!("已发送音频包: {} / frame_size={}samples / encoded_size={}B", cnt, frame.len(), payload.len()); 
                                                                }
                                                            }
                                                        });
                                                    }
                                                },
                                                Ok(CallEvent::Terminated) => {
                                                    stop_for_loop.store(true, std::sync::atomic::Ordering::SeqCst);
                                                    let _ = crate::services::call::CallService::update_status(&call_id_for_loop, CallStatus::Connected, Some(0)).await;
                                                    let _ = app_inside.emit("call_event", serde_json::json!({"type":"terminated"}));
                                                    break;
                                                }
                                                Err(e) => {
                                                    stop_for_loop.store(true, std::sync::atomic::Ordering::SeqCst);
                                                    let _ = crate::services::call::CallService::update_status(&call_id_for_loop, CallStatus::Failed, None).await;
                                                    let _ = app_inside.emit("call_event", serde_json::json!({"type":"error","message": e.to_string()}));
                                                    break;
                                                }
                                            }
                                        }
                                        _ = tokio::time::sleep(Duration::from_millis(100)) => {
                                            if stop_for_loop.load(std::sync::atomic::Ordering::SeqCst) {
                                                log::info!("呼叫已建立，发送 BYE 请求结束通话");
                                                let _ = crate::services::call::CallService::update_status(&call_id_for_loop, CallStatus::Cancelled, None).await;
                                                match call.terminate().await { 
                                                    Ok(_) => log::info!("成功发送 BYE 请求"), 
                                                    Err(e) => log::warn!("发送 BYE 失败: {}", e) 
                                                }
                                                let _ = app_inside.emit("call_event", serde_json::json!({"type":"terminated"}));
                                                break;
                                            }
                                        }
                                    }
                                }
                                let mut state = GLOBAL_STATE.lock().await; 
                                state.current_call_stop = None;
                            }
                            Err(e) => { 
                                log::error!("完成呼叫失败: {}", e); 
                                let _ = app_for_loop.emit("call_event", serde_json::json!({"type":"error","message": e.to_string()})); 
                            }
                        }
                    }
                    Err(e) => {
                        let _ = crate::services::call::CallService::update_status(&call_id_for_loop, CallStatus::Failed, None).await;
                        let _ = app_for_loop.emit("call_event", serde_json::json!({"type":"error","message": e.to_string()}));
                        let mut state = GLOBAL_STATE.lock().await; 
                        state.current_call_stop = None;
                    }
                }
            }
        });
        Ok(MakeCallResult { success: true, message: format!("已向 {} 发起呼叫", target) })
    }

    pub async fn hangup_call() -> Result<ConnectionResult, String> { use std::sync::atomic::Ordering; let guard = crate::models::state::GLOBAL_STATE.lock().await; if let Some(flag) = &guard.current_call_stop { flag.store(true, Ordering::SeqCst); Ok(ConnectionResult { success: true, message: "已请求挂断当前通话".to_string() }) } else { Ok(ConnectionResult { success: false, message: "当前无活动通话".to_string() }) } }

    pub fn compute_frame_samples(clock_rate: u32, frame_ms: u32) -> usize { (clock_rate * frame_ms / 1000) as usize }

    pub fn make_exact_frame(mut samples: Vec<i16>, frame_samples: usize) -> Vec<i16> { if samples.len() == frame_samples { samples } else if samples.len() > frame_samples { samples.truncate(frame_samples); samples } else { samples.resize(frame_samples, 0); samples } }

    pub fn spawn_audio_player_thread(stop: std::sync::Arc<AtomicBool>) -> std_mpsc::Sender<(Vec<i16>, u32, u32)> {
        let (audio_tx, audio_rx) = std_mpsc::channel::<(Vec<i16>, u32, u32)>();
        let _audio_thread = thread::spawn(move || {
            let mut player = match crate::services::audio::AudioPlayer::new() { Ok(p) => p, Err(e) => { log::error!("音频播放器初始化失败: {}", e); return; } };
            while !stop.load(std::sync::atomic::Ordering::SeqCst) {
                match audio_rx.recv_timeout(Duration::from_millis(100)) {
                    Ok((samples, sample_rate, channels)) => { if let Err(e) = player.play_audio(&samples, sample_rate, channels) { log::error!("音频播放失败: {}", e); } }
                    Err(std_mpsc::RecvTimeoutError::Timeout) => continue,
                    Err(std_mpsc::RecvTimeoutError::Disconnected) => break,
                }
            }
        });
        audio_tx
    }

    pub fn spawn_mic_thread(clock_rate: u32, channels: u32, q2: std::sync::Arc<AsyncMutex<VecDeque<Vec<i16>>>>, stop: std::sync::Arc<AtomicBool>, frame_ms: u32) -> thread::JoinHandle<()> {
        thread::spawn(move || {
            let mut rec = match AudioRecorder::new(clock_rate, channels) { Ok(r) => r, Err(e) => { log::error!("音频录音器初始化失败: {}", e); return; } };
            let frame_samples = Self::compute_frame_samples(clock_rate, frame_ms);
            let mut audio_buffer = Vec::new();
            loop {
                if stop.load(std::sync::atomic::Ordering::SeqCst) { log::info!("停止标志触发：麦克风线程退出"); break; }
                match rec.read_audio() {
                    Ok(buf) => { if !buf.is_empty() { audio_buffer.extend_from_slice(&buf); while audio_buffer.len() >= frame_samples { let frame: Vec<i16> = audio_buffer.drain(0..frame_samples).collect(); let mut q = q2.blocking_lock(); q.push_back(frame); if q.len() > 10 { q.pop_front(); } } } }
                    Err(e) => { log::error!("读取音频失败: {}", e); std::thread::sleep(Duration::from_millis(50)); }
                }
                std::thread::sleep(Duration::from_millis(5));
            }
        })
    }
}

// CallRuntimeService 内联实现